home *** CD-ROM | disk | FTP | other *** search
- From: koreth%panarthea.ebay@sun.com (Steven Grimm)
- Newsgroups: comp.sources.atari.st
- Subject: v02i063: crunch -- Executable file compressor
- Keywords: 68000
- Approved: koreth%panarthea.ebay@sun.com
-
- Submitted-by: usqb015@liverpool.ac.uk (Mark Powell)
- Posting-number: Volume 2, Issue 63
- Archive-name: crunch
-
- [Binary and docs are in comp.binaries.atari.st. -sg]
-
- * Program file Cruncher
- * Copyright 1989 By M.S.Powell (usqb015@uk.ac.liv)
- * Permission granted to examine and modify this source for; personal use,
- * no profit and as long as this header is left intact.
- * Written on Devpac v1.22 by Hisoft
-
- * Examine command line
-
- move.l 4(sp),a5
-
- lea 129(a5),a5
- cmp.b #'-',(a5)
- bne.s nxtfield
- addq.l #1,a5
- chkqual move.b (a5)+,d0
- cmp.b #$d,d0
- beq invalid
- cmp.b #' ',d0
- beq.s nxtfield
- cmp.b #'D',d0
- bne.s notd
- move #1,delete
- notd cmp.b #'H',d0
- bne.s noth
- move #1,hold
- noth cmp.b #'U',d0
- bne.s notu
- move #1,uncrunch
- notu cmp.b #'I',d0
- bne.s chkqual
- move #1,ignore
- bra.s chkqual
-
- nxtfield
- cmp.b #' ',(a5)
- bne.s getname1
- addq.l #1,a5
- bra.s nxtfield
- getname1
- cmp.b #$d,(a5)
- beq invalid
- move.l a5,sourcenamepnt
- getname1loop
- move.b (a5)+,d0
- cmp.b #$d,d0
- beq.s fndend1
- cmp.b #' ',d0
- bne.s getname1loop
- fndend1 subq.l #1,a5
- move.l a5,sourcenameend
- bra.s intro
-
- invalid clr cmndlnokay
-
- * Intro procedure
-
- intro lea mainmess(pc),a0
- bsr print
-
- tst cmndlnokay
- bne.s clokay
-
- lea instructions(pc),a0
- bsr print
- bra finished
-
- clokay pea dta(pc) set dta buffer
- move #$1a,-(sp)
- trap #1
- addq.l #6,sp
-
- clr -(sp) Search for source file
- move.l sourcenamepnt(pc),-(sp)
- move #$4e,-(sp)
- trap #1
- addq.l #8,sp
- move d0,error
- beq nextfile
-
- lea nomatch(pc),a0
- bsr print
- bra finished
-
- * Main loop
-
- nextfile
- lea dta+30(pc),a0
- move.l sourcenameend(pc),a1
- move.l sourcenamepnt(pc),a2
- look_for_name_start
- move.b -(a1),d0
- cmp.b #'\',d0
- beq.s addname
- cmp.b #':',d0
- beq.s addname
- cmp.l a2,a1
- bge.s look_for_name_start
-
- addname moveq #0,d1
- addq.l #1,a1
- anamlp move.b (a0)+,d0
- move.b d0,(a1)+
- beq.s done_name
- cmp.b #'.',d0
- bne.s anamlp
- moveq #1,d1
- move.l a1,sourcenameext
- bra.s anamlp
- done_name
- tst d1
- bne.s do_it
- move.l a1,sourcenameext
- do_it bra do_your_stuff
- return
- tst error
- beq.s noerror
-
- tst ignore
- beq.s finished
-
- noerror move #$4f,-(sp)
- trap #1
- addq.l #2,sp
- tst d0
- beq.s nextfile
-
- finished
- tst hold
- beq.s nohold
-
- lea pressany(pc),a0
- bsr print
- bsr.s anykey
-
- nohold move error(pc),-(sp) Return error code to calling
- move #$4c,-(sp) program
- trap #1
-
- anykey pea $20002
- trap #13
- addq.l #4,sp
- rts
-
- prchar move d0,-(sp)
- pea $30002
- trap #13
- addq.l #6,sp
- rts
-
-
- * Main loop body
-
- do_your_stuff
- move.l sp,stack
-
- lea reading(pc),a0
- bsr print
- bsr printfilename
-
- move.l sp,a6
- sub.l #4096,a6 a6=top of free memory
- move.l dta+26(pc),d6 d6=file length
- cmp.l #28,d6
- blt.s not_a_program
-
- lea buffer(pc),a0
- add.l d6,a0
- cmp.l a6,a0
- bgt outofmemory
-
- * Read in file
-
- lea buffer(pc),a3
- clr -(sp)
- move.l sourcenamepnt(pc),-(sp)
- move #$3d,-(sp)
- trap #1
- addq.l #8,sp
- tst.l d0
- bmi fileerror
-
- move d0,d7
- pea (a3) Read first 2 bytes, to check if it is
- pea 2.w a valid GEMDOS program
- move d0,-(sp)
- move #$3f,-(sp)
- trap #1
- lea 12(sp),sp
- tst.l d0
- bmi fileerror
- cmp #$601a,(a3)
- beq.s a_prog
-
- not_a_program
- lea notprog(pc),a0
- bsr print
- bra exit
-
- a_prog pea 2(a3)
- move.l d6,-(sp)
- move d7,-(sp)
- move #$3f,-(sp)
- trap #1
- lea 12(sp),sp
- tst.l d0
- bmi fileerror
-
- move d7,-(sp)
- move #$3e,-(sp)
- trap #1
- addq.l #4,sp
-
- * Check if file is already crunched
-
- lea buffer+$1c(pc),a0
- lea header+$1c(pc),a1
- move #lengthoftable-header-$1c-1,d0
- chklp cmpm.b (a0)+,(a1)+
- dbne d0,chklp
- bne crunchfile
-
- * If file is already crunched, then uncrunch it
-
- tst uncrunch
- bne.s uncrunchit
-
- lea crunched(pc),a0
- bsr print
- bra exit
-
- uncrunchit
- lea uncrunching(pc),a0
- bsr print
-
- lea buffer+(lengthoftable-header)(pc),a0
- lea buffer-lengthoftable(a0),a3
- move.l (a0)+,a4
- add.l a3,a4
- move.l (a0)+,a5
- add.l a4,a5
-
- move.l (a0)+,d0
- move.l (a3),d1
- and.l #$ffffff,d1
- lea 0(a4,d1.l),a0
- move.l a0,a2
- lea 0(a5,d0.l),a1
- cmp.l a6,a1
- bgt outofmemory
- move.l a1,a6
- moveup1 move.b -(a5),-(a1)
- cmp.l a5,a0
- bne.s moveup1
- move.l a6,a5
- move.l a1,a6
-
- uncrunchloop1
- move.l (a3)+,d1
- move.l d1,d2
- rol.l #8,d2
- and.l #$ffffff,d1
- moveq #0,d3
- move (a3)+,d3
- bne.s not103
- move.l #65536,d3
- not103 add.l d0,d1
- sub.l d3,d0
- lea 0(a4,d1.l),a0
- cmp.l a6,a0
- beq.s nomove12
- movebitdown1
- move.b (a6)+,(a2)+
- cmp.l a6,a0
- bne.s movebitdown1
- nomove12
- subq #1,d3
- makeblock1
- move.b d2,(a2)+
- dbra d3,makeblock1
- tst.l d0
- bne.s uncrunchloop1
-
- move.l a5,a3
- sub.l a4,a3
-
- tst delete
- beq writefile
- move.l sourcenameext(pc),a0
- move.b #'.',-1(a0)
- move.b #'U',(a0)+
- move.b #'C',(a0)+
- move.b #'R',(a0)+
- bra writefile
-
- * Crunch a file
-
- crunchfile
- tst uncrunch
- beq.s okaycf
-
- lea notcrunched(pc),a0
- bsr print
- bra exit
-
- okaycf lea crunching(pc),a0
- bsr print
-
- move.l a6,a5
- sub.l d6,a5
- move.l a6,a4
- lea 0(a3,d6.l),a3
- moveprogup
- move.b -(a3),-(a4)
- cmp.l a4,a5
- bne.s moveprogup
-
- lea buffer(pc),a4
- lea -6(a6),a2
- move.l 2(a4),d7
- add.l 6(a4),d7
- add.l $a(a4),d7 d7=total original length
-
- move.l a5,a0
- p1lp moveq #0,d0
- move.b (a0),d0
- cmp.b 1(a0),d0
- bne.s notsam
- cmp.b 2(a0),d0
- bne.s notsam
- cmp.b 3(a0),d0
- bne.s notsam
- cmp.b 4(a0),d0
- bne.s notsam
- cmp.b 5(a0),d0
- bne.s notsam
- cmp.b 6(a0),d0
- bne.s notsam
-
- lea 7(a0),a1
- fndend cmp.l a6,a1
- bgt.s endprog
- cmp.b (a1)+,d0
- beq.s fndend
- endprog move.l a0,d1
- sub.l a5,d1
- ror.l #8,d0
- or.l d0,d1
- subq.l #1,a1
- move.l a1,d2
- sub.l a0,d2
- nextbit cmp.l #65536,d2
- ble.s lastbit
- move.l d1,(a4)+
- add.l #65536,d1
- clr (a4)+
- sub.l #65536,d2
- bra.s nextbit
- lastbit move.l d1,(a4)+
- move d2,(a4)+
- cmp.l a5,a4
- bge outofmemory
- lea -1(a1),a0
-
- notsam addq.l #1,a0
- cmp.l a2,a0
- blt.s p1lp
-
- lea buffer+4(pc),a3
- cmp.l a3,a4 Is table empty?
- blt hopeless
- move.l a4,-(sp)
- moveq #0,d1
- move -(a4),d1
- bne.s not0
- move.l #65536,d1
- not0 move.l -4(a4),d2
- and.l #$ffffff,d2
- add.l d1,d2
- lea 0(a5,d2.l),a2
- cmp.l a4,a3
- beq.s lastblock
- crunchloop
- move.l -(a4),d2
- and.l #$ffffff,d2
- lea 0(a5,d2.l),a1
- moveq #0,d1
- move -(a4),d1
- bne.s not01
- move.l #65536,d1
- not01 move.l -4(a4),d2
- and.l #$ffffff,d2
- add.l d1,d2
- lea 0(a5,d2.l),a0
- cmp.l a1,a0
- beq.s nomove
- removeblock
- move.b -(a1),-(a2)
- cmp.l a1,a0
- bne.s removeblock
- nomove cmp.l a4,a3
- bne.s crunchloop
-
- lastblock
- move.l -(a4),d1
- and.l #$ffffff,d1
- lea 0(a5,d1.l),a1
- cmp.l a5,a1
- beq.s nomove1
- removelastblock
- move.b -(a1),-(a2)
- cmp.l a5,a1
- bne.s removelastblock
- nomove1 move.l a2,a5
-
- move.l (sp)+,a4
-
- * Add uncrunch program
-
- done move.l a4,a3
- move.l a5,a2 attach crunched prog to end of table
- moveprog
- move.b (a2)+,(a3)+
- cmp.l a2,a6
- bne.s moveprog
-
- move.l a3,d0
- sub.l a4,d0
- move.l d0,lengthofprog
-
- move.l a4,d0
- lea buffer(pc),a2
- sub.l a2,d0
- move.l d0,lengthoftable
-
- moveq #0,d1
- getlengthloop
- addq.l #4,a2
- moveq #0,d0
- move (a2)+,d0
- bne.s not02
- move.l #65536,d0
- not02 add.l d0,d1
- cmp.l a2,a4
- bne.s getlengthloop
- move.l d1,totallength
-
- lea header(pc),a4
- sub.l a4,a3
- move.l a3,d0
- add.l #1023,d0
- and.l #$fffc00,d0
- add.l #1023,d6
- and.l #$fffc00,d6
- cmp.l d0,d6
- ble hopeless
- lea -$1c(a3),a0
- move.l a0,2(a4)
- sub.l a0,d7
- move.l d7,$a(a4)
-
- tst delete
- beq.s writefile
- move.l sourcenameext(pc),a0
- move.b #'.',-1(a0)
- move.b #'C',(a0)+
- move.b #'R',(a0)+
- move.b #'N',(a0)+
-
- writefile
- lea writing(pc),a0
- bsr print
- bsr printfilename
-
- clr -(sp)
- move.l sourcenamepnt(pc),-(sp)
- move #$3c,-(sp)
- trap #1
- addq.l #8,sp
- tst.l d0
- bmi fileerror
-
- move d0,-(sp)
- pea (a4)
- pea (a3)
- move d0,-(sp)
- move #$40,-(sp)
- trap #1
- lea 12(sp),sp
- tst.l d0
- bmi fileerror
-
- move #$3e,-(sp)
- trap #1
- addq.l #4,sp
- tst.l d0
- bmi fileerror
-
- exit move.l stack(pc),sp
- bra return
-
-
-
- * Error routines
-
- outofmemory
- lea outmem(pc),a0
- bsr.s print
- move #-39,error
- bra.s exit
-
- fileerror
- move d0,error
- lea generror(pc),a0
- bsr.s print
- bra.s exit
-
- hopeless
- lea nohope(pc),a0
- bsr.s print
- bra.s exit
-
- print pea (a0)
- move #9,-(sp)
- trap #1
- addq.l #6,sp
- rts
-
- printfilename
- move.l sourcenamepnt(pc),a5 Print file name
- prnamlp move.b (a5)+,d0
- beq.s donenameprint
- bsr prchar
- bra.s prnamlp
- donenameprint
- moveq #13,d0
- bsr prchar
- moveq #10,d0
- bra prchar
-
- find_target_file_ext
- lea dta+30(pc),a0
- lookext move.b (a0)+,d0
- beq.s fndext
- cmp.b #'.',d0
- bne.s lookext
-
- fndext move.b #'.',-1(a0)
- rts
-
-
- * Various data
-
- mainmess
- dc.b 27,'vProgram file cruncher V3.2',13,10,13,10
- dc.b 'Copyright 4/9/1988 By M.S.Powell',13,10,0
- instructions
- dc.b 13,10,'Usage:',13,10,13,10
- dc.b 'crunch [h][d][u] <pathname> ',13,10,13,10
- dc.b 'h hold screen before exiting',13,10
- dc.b 'd disable deletion of original file',13,10
- dc.b 'u uncrunch files',13,10,0
-
- nomatch dc.b 13,10,'No files match pathname',13,10,0
- reading dc.b 13,10,'Reading ',0
- writing dc.b 'Writing ',0
-
- crunched
- dc.b 'File already crunched',13,10,0
- notprog
- dc.b 'Not a GEMDOS program file',13,10,0
- notcrunched
- dc.b 'File not crunched',13,10,0
- uncrunching
- dc.b 'Uncrunching...',13,10,0
- crunching
- dc.b 'Crunching...',13,10,0
-
- outmem dc.b 'Out of memory',13,10,0
- nohope dc.b 'File uncrunchable',13,10,0
- generror
- dc.b 'A file error has occured',13,10,0
- pressany
- dc.b 13,10,'Press any key ',0
- even
-
- stack dc.l 0
- error dc.w 0
- cmndlnokay
- dc.w 1
-
- delete dc.w 0
- hold dc.w 0
- uncrunch
- dc.w 0
- ignore dc.w 0
-
- sourcenamepnt
- dc.l 0
- sourcenameend
- dc.l 0
- sourcenameext
- dc.l 0
-
- even
-
- dta ds.b 44
-
-
- * GEMDOS header
-
- header dc.w $601a
- dc.l 0,0,0,0,0,0
- dc.w $ffff
-
- * Uncrunch routine
-
- uncrunchprog
- clr.l -(sp)
- move #32,-(sp)
- trap #1
- addq.l #6,sp
- move.l d0,-(sp)
-
- move $8240.w,-(sp)
-
- lea start(pc),a3
- move.l lengthoftable(pc),a4
- add.l a3,a4
- move.l lengthofprog(pc),a5
- add.l a4,a5
-
- move.l totallength(pc),d0
- move.l (a3),d1
- and.l #$ffffff,d1
- lea 0(a4,d1.l),a0
- move.l a0,a2
- lea 0(a5,d0.l),a1
- move.l a1,a6
- moveup move.b -(a5),-(a1)
- cmp.l a5,a0
- bne.s moveup
- move.l a6,a5
- move.l a1,a6
-
- uncrunchloop
- move d5,$8240.w
- add #$89,d5
- and #$777,d5
- or #$333,d5
- move.l (a3)+,d1
- move.l d1,d2
- rol.l #8,d2
- and.l #$ffffff,d1
- moveq #0,d3
- move (a3)+,d3
- bne.s not03
- move.l #65536,d3
- not03 add.l d0,d1
- sub.l d3,d0
- lea 0(a4,d1.l),a0
- cmp.l a6,a0
- beq.s nomove2
- movebitdown
- move.b (a6)+,(a2)+
- cmp.l a6,a0
- bne.s movebitdown
- nomove2 subq #1,d3
- makeblock
- move.b d2,(a2)+
- dbra d3,makeblock
- tst.l d0
- bne.s uncrunchloop
-
- * move relocate program to end of text
-
- doneuncrunch
- move.l a5,d0
- addq.l #1,d0
- and #$fffe,d0
- move.l d0,a1
- move.l d0,a2
- lea relocate(pc),a0
- move #start-relocate-1,d0
- movereloc
- move.b (a0)+,(a1)+
- dbra d0,movereloc
- jmp (a2)
-
- relocate
- move (sp)+,$8240.w
- move.l 8(sp),a0 a0=start of base page
- lea $100(a0),a1 a1=start of text area
- move.l a1,a2
- move.l a0,(a0)+ base address of TPA
- move.l $436.w,(a0)+ end of TPA+1
- move.l a1,(a0)+ base address of text
- move.l 2(a4),(a0)+ length of text
- add.l 2(a4),a1
- move.l a1,(a0)+ base address of data
- move.l 6(a4),(a0)+ length of data
- add.l 6(a4),a1
- move.l a1,(a0)+ base address of bss
- move.l $a(a4),(a0)+ length of bss
- move.l a1,-(sp)
- move.l $a(a4),-(sp)
- add.l $e(a4),a1 a1=address of relocation data
- tst $1a(a4)
- bpl.s relocpres
- sub.l a1,a1 a1=0 if no reloc. data
- relocpres
- lea $1c(a4),a4
- move.l a2,a3 a3=start of text
- clr.b (a5)
- movetextdown
- move.l (a4)+,(a2)+
- cmp.l a5,a4
- blt.s movetextdown
- moveq #0,d7
- cmp.l d7,a1
- beq.s execute
-
- * Relocate text
-
- move.l a3,a6 a6=start of text
-
- move.l a6,d0
- move.l (a1)+,d1
- beq.s execute
- add.l d1,a6
- add.l d0,(a6)
- moveq #1,d2
- move.l #$fe,d3
- moveq #0,d1
- reloclp move.b (a1)+,d1
- beq.s execute
- cmp.b d2,d1
- beq.s disp
- add.l d1,a6
- add.l d0,(a6)
- bra.s reloclp
- disp add.l d3,a6
- bra.s reloclp
-
- execute move.l (sp)+,d5 d5=length of bss
- move.l (sp)+,a4 a4=start of bss
- move #32,-(sp)
- trap #1
- addq.l #6,sp
-
- lea start_bss_clearer(pc),a0
- move.l d5,d6
- add.l a4,d6
- addq.l #1,d6
- and #$fffe,d6
- move.l d6,a5
- move.l a5,a6
- move.l (a0)+,(a5)+
- move.l (a0)+,(a5)+
- jmp (a6)
-
- start_bss_clearer
- move.b d7,(a4)+
- cmp.l a6,a4
- blt.s start_bss_clearer
- runit jmp (a3)
- end
-
- lengthoftable dc.l 0
- lengthofprog dc.l 0
- totallength dc.l 0
- start
- buffer
-
-